home *** CD-ROM | disk | FTP | other *** search
- /*
- File: DisplayVideo.c
-
- Description:DisplayVideo will display all info about all video modes supported
- by each installed video card with their attached monitor. The purpose
- of this code is to provide a sample of how developers can discover the
- bit depths and timings of multisync displays.
-
- Author: EWA
- Copyright: Copyright: © 1995-1999 by Apple Computer, Inc.
- all rights reserved.
-
- Disclaimer: You may incorporate this sample code into your applications without
- restriction, though the sample code has been provided "AS IS" and the
- responsibility for its operation is 100% yours. However, what you are
- not permitted to do is to redistribute the source as "DSC Sample Code"
- after having made changes. If you're going to re-distribute the source,
- we require that you make it clear in the source that the code was
- descended from Apple Sample Code, but that you've made changes.
-
- Change History (most recent first):
- 6/24/99 Updated for Metrowerks Codewarror Pro 2.1(KG)
- 1/28/97 Updated source for Metrowerks CodeWarrior 11 Fixed up
- formatting and generally made things nicer(EWA)
- 5/24/95 New today(EWA)
-
- */
-
-
- #include <Dialogs.h>
- #include <Devices.h>
- #include <Displays.h>
- #include <Errors.h>
- #include <FixMath.h>
- #include <fp.h>
- #include <Gestalt.h>
- #include <Memory.h>
- #include <Palettes.h>
- #include <PLStringFuncs.h>
- #include <QuickDraw.h>
- #include <ROMDefs.h>
- #include <Slots.h>
- #include <StdIO.h>
- #include <Video.h>
- #include <TextUtils.h>
- #include <Strings.h>
- #include <DriverServices.h>
-
- #include <stdlib.h>
-
- //--------------------------------------------------------------
- //
- // Internal defines, structs, typedefs, and routine declarations
- //
- //--------------------------------------------------------------
- struct DepthInfo {
- VDSwitchInfoRec depthSwitchInfo; // This is the switch mode to choose this timing/depth
- VPBlock depthVPBlock; // VPBlock (including size, depth and format)
- };
- typedef struct DepthInfo DepthInfo;
-
- struct ListIteratorDataRec {
- unsigned long displayModeFlags; //
- VDSwitchInfoRec displayModeSwitchInfo; //
- VDResolutionInfoRec displayModeResolutionInfo; //
- VDTimingInfoRec displayModeTimingInfo; // Contains timing flags and such
- unsigned long depthBlockCount; // How many depths available for a particular timing
- DepthInfo *depthBlocks; // Array of DepthInfo
- Str255 displayModeName; // name of the timing mode
- };
- typedef struct ListIteratorDataRec ListIteratorDataRec;
-
- void PrintCurrentVideoSetting (GDHandle walkDevice);
-
- void DisplayVideoSettings (void);
-
- void PrintAvailableVideoSettingsDM1 (GDHandle walkDevice);
-
- void PrintAvailableVideoSettingsDM2 (GDHandle walkDevice,
- DMDisplayModeListIteratorUPP myModeIteratorProc,
- DMListIndexType theDisplayModeCount,
- DMListType *theDisplayModeList);
-
- pascal void ModeListIterator ( void *userData,
- DMListIndexType itemIndex,
- DMDisplayModeListEntryPtr displaymodeInfo);
-
- // routine implementations
- void main(void)
- {
- DisplayVideoSettings ();
- }
-
-
- //--------------------------------------------------------------
- //
- // Implementation of sample code
- //
- //--------------------------------------------------------------
- void PrintCurrentVideoSetting (GDHandle walkDevice)
- {
- unsigned long displayMgrVersion;
- OSErr error = paramErr;
- CntrlParam pBlock;
- VDSwitchInfoRec switchInfo;
- AuxDCEHandle theDCE;
- VDSwitchInfoRec videoMode;
-
- Gestalt(gestaltDisplayMgrVers, (long*)&displayMgrVersion);
- if (displayMgrVersion >= 0x00020000)
- { // get the info the DM 2.0 way
- error = DMGetDisplayMode(walkDevice, &switchInfo);
- if (noErr == error)
- {
- printf ("Current Settings DM2 - displayMode: %d, depthMode: %d\n", switchInfo.csData, switchInfo.csMode);
- }
- return;
- }
- else
- { // get the info the DM 1.0 way
- videoMode.csMode = -1; // init to bogus value
- videoMode.csData = -1; // init to bogus value
- pBlock.ioNamePtr = nil;
- pBlock.ioCRefNum = (*(walkDevice))->gdRefNum;
- pBlock.csCode = cscGetCurMode;
- *(Ptr *)&pBlock.csParam[0] = (Ptr)&videoMode;
-
- error = PBStatusSync((ParmBlkPtr )&pBlock); // ask the driver first....since we trust it the most
-
- if ( noErr == error && ((-1 == videoMode.csMode) || (-1 == videoMode.csData)) )
- error = statusErr;
-
- if (noErr != error) // if the driver has no clue fill it videoMode by hand as a last resort
- {
- theDCE = (AuxDCEHandle)GetDCtlEntry((*(walkDevice))->gdRefNum);
-
- if( theDCE )
- {
- videoMode.csData = (unsigned char)(*theDCE)->dCtlSlotId;
- videoMode.csMode = (*(walkDevice))->gdMode;
- error = noErr;
- }
- }
- if (noErr == error)
- {
- printf ("Current Settings DM1 - displayMode: %d, depthMode: %d\n", videoMode.csData, videoMode.csMode);
- }
- return;
- }
- }
-
-
- void DisplayVideoSettings (void)
- {
- Boolean displayMgrPresent;
- short iCount = 0; // just a counter of GDevices we have seen
- DMDisplayModeListIteratorUPP myModeIteratorProc = nil; // for DM2.0 searches
- SpBlock spBlock;
- Boolean suppliedGDevice;
- DisplayIDType theDisplayID; // for DM2.0 searches
- DMListIndexType theDisplayModeCount; // for DM2.0 searches
- DMListType theDisplayModeList; // for DM2.0 searches
- long value = 0;
- GDHandle walkDevice = nil; // for everybody
-
- Gestalt(gestaltDisplayMgrAttr,&value);
- displayMgrPresent=value&(1<<gestaltDisplayMgrPresent);
- displayMgrPresent=displayMgrPresent && (SVersion(&spBlock)==noErr); // need slot manager
- if (displayMgrPresent) // and Display Manager
- {
- walkDevice = DMGetFirstScreenDevice (dmOnlyActiveDisplays); // for everybody
- suppliedGDevice = false;
-
- myModeIteratorProc = NewDMDisplayModeListIteratorProc(ModeListIterator); // for DM2.0 searches
-
- // Note that we are hosed if somebody changes the gdevice list behind our backs while we are iterating....
- // ...now do the loop if we can start
- if( walkDevice && myModeIteratorProc) do // start the search
- {
- iCount++; // GDevice we are looking at (just a counter)
- printf("=================================================\n");
- printf("GDevice #%d (0x%X) at location (%d,%d).\n",iCount, *walkDevice, (long )(*walkDevice)->gdRect.left, (long )(*walkDevice)->gdRect.top);
- printf("=================================================\n\n");
-
- PrintCurrentVideoSetting (walkDevice);
-
- if( noErr == DMGetDisplayIDByGDevice( walkDevice, &theDisplayID, false ) ) // DM1.0 does not need this, but it fits in the loop
- {
- theDisplayModeCount = 0; // for DM2.0 searches
- if (noErr == DMNewDisplayModeList(theDisplayID, 0, 0, &theDisplayModeCount, &theDisplayModeList) )
- {
- // search NuBus & PCI the new kool way through Display Manager 2.0
- // printf("\nAvailable Video Settings DM2.0 way\n");
- PrintAvailableVideoSettingsDM2 (walkDevice, myModeIteratorProc, theDisplayModeCount, &theDisplayModeList);
- DMDisposeList(theDisplayModeList); // now toss the lists for this gdevice and go on to the next one
- }
- else
- {
- // search NuBus only the old disgusting way through the slot manager
- printf("\nAvailable Video Settings DM1.0 way\n");
- PrintAvailableVideoSettingsDM1 (walkDevice);
- }
- }
-
- printf("\n\n\n");
-
- } while ( !suppliedGDevice && nil != (walkDevice = DMGetNextScreenDevice ( walkDevice, dmOnlyActiveDisplays )) ); // go until no more gdevices
- if( myModeIteratorProc )
- DisposeRoutineDescriptor(myModeIteratorProc);
- return;
- }
- }
-
- void PrintAvailableVideoSettingsDM1 (GDHandle walkDevice)
- {
- AuxDCEHandle myAuxDCEHandle;
- unsigned long depthMode;
- unsigned long displayMode;
- OSErr error;
- OSErr errorEndOfTimings;
- short height;
- short jCount = 0;
- Boolean modeOk;
- SpBlock spAuxBlock;
- SpBlock spBlock;
- unsigned long switchFlags;
- VPBlock *vpData;
- short width;
-
- myAuxDCEHandle = (AuxDCEHandle) GetDCtlEntry((**walkDevice).gdRefNum);
- spBlock.spSlot = (**myAuxDCEHandle).dCtlSlot;
- spBlock.spID = (**myAuxDCEHandle).dCtlSlotId;
- spBlock.spExtDev = (**myAuxDCEHandle).dCtlExtDev;
- spBlock.spHwDev = 0; // we are going to get this pup
- spBlock.spParamData = 1<<foneslot; // this slot, enabled, and it better be here.
- spBlock.spTBMask = 3; // don't have constants for this yet
- errorEndOfTimings = SGetSRsrc(&spBlock); // get the spDrvrHW so we know the ID of this puppy. This is important
- // since some video cards support more than one display, and the spDrvrHW
- // ID can, and will, be used to differentiate them.
-
- if ( noErr == errorEndOfTimings )
- {
- // reinit the param block for the SGetTypeSRsrc loop, keep the spDrvrHW we just got
- spBlock.spID = 0; // start at zero,
- spBlock.spTBMask = 2; // 0b0010 - ignore DrvrSW - why ignore the SW side? Is it not important for video?
- spBlock.spParamData = (1<<fall) + (1<<foneslot) + (1<<fnext); // 0b0111 - this slot, enabled or disabled, so we even get 640x399 on Blackbird
- spBlock.spCategory=catDisplay;
- spBlock.spCType=typeVideo;
- errorEndOfTimings = SGetTypeSRsrc(&spBlock); // but only on 7.0 systems, not a problem since we require DM1.0
-
- // now, loop through all the timings for this GDevice
- if ( noErr == errorEndOfTimings ) do
- {
- // now, loop through all possible depth modes for this timing mode
- displayMode = (unsigned char)spBlock.spID; // "timing mode, ie:resource ref number"
- for (jCount = firstVidMode; jCount<= sixthVidMode; jCount++)
- {
- depthMode = jCount; // vid mode
- error = DMCheckDisplayMode(walkDevice,displayMode,depthMode,&switchFlags,0,&modeOk);
-
- // only if the mode okay
- if (noErr == error && modeOk)
- {
- // have a good displayMode/depthMode combo - now lets look inside
- spAuxBlock = spBlock; // don't ruin the iteration spBlock!!
- spAuxBlock.spID = depthMode; // vid mode
- error=SFindStruct(&spAuxBlock); // get back a new spsPointer
- if (noErr == error) // keep going if no error…
- {
- spAuxBlock.spID = 0x01; // mVidParams request
- error=SGetBlock (&spAuxBlock); // use the new spPointer and get back...a NewPtr'ed spResult
- if (noErr == error) // …keep going if no error…
- { // We have data! lets have a look
- vpData = (VPBlock*)spAuxBlock.spResult;
- height = vpData->vpBounds.bottom; // left and top are usually zero
- width = vpData->vpBounds.right;
-
- // print screen data
- printf("\nTiming Mode: %d\n", displayMode);
- printf("Depth Mode: %d, Depth: %d, Resolution: %dH x %dV\n",
- depthMode,
- vpData->vpPixelSize,
- vpData->vpBounds.right,
- vpData->vpBounds.bottom);
- printf("Components per Pixel: %d, bits per Component: %d\n",
- vpData->vpCmpCount,
- vpData->vpCmpSize);
- printf("Switch flags:\n");
- if (switchFlags & 1<<kNoSwitchConfirmBit)
- printf(" Confirmation not required,\n");
- else
- printf(" Confirmation required,\n");
- if (switchFlags & 1<<kDepthNotAvailableBit)
- printf(" Current depth not available in this mode,\n");
- else
- printf(" Current depth available in this mode,\n");
- if (switchFlags & 1<<kShowModeBit)
- printf(" Always shown,\n");
- else
- printf(" Not always shown,\n");
- if (switchFlags & 1<<kModeNotResizeBit)
- printf(" Not resizeable,\n");
- else
- printf(" Resizeable\n");
-
- if (spAuxBlock.spResult) DisposePtr ((Ptr)spAuxBlock.spResult); // toss this puppy when done
- }
- }
- }
- }
- // go around again, looking for timing modes for this GDevice
- spBlock.spTBMask = 2; // ignore DrvrSW
- spBlock.spParamData = (1<<fall) + (1<<foneslot) + (1<<fnext); // next resource, this slot, whether enabled or disabled
- errorEndOfTimings = SGetTypeSRsrc(&spBlock); // and get the next timing mode
- } while ( noErr == errorEndOfTimings ); // until the end of this GDevice
- }
-
- }
-
- pascal void ModeListIterator(void *userData, DMListIndexType, DMDisplayModeListEntryPtr displaymodeInfo)
- {
- unsigned long depthCount;
- short iCount;
- ListIteratorDataRec *myIterateData = (ListIteratorDataRec*) userData;
- DepthInfo *myDepthInfo;
-
- // printf ("\n now in ModeListIterator\n");
- // set display data in a round about way
- // Set the basics
- myIterateData->displayModeFlags = displaymodeInfo->displayModeFlags; // Info on this particular display mode
- myIterateData->displayModeSwitchInfo = *displaymodeInfo->displayModeSwitchInfo; // not needed - depth info has this per depth
- myIterateData->displayModeResolutionInfo = *displaymodeInfo->displayModeResolutionInfo; // refresh rate, pixels/lines at max depth
- myIterateData->displayModeTimingInfo = *displaymodeInfo->displayModeTimingInfo; // to get the flags on timing mode
- PStrCopy ((StringPtr)&myIterateData->displayModeName, (ConstStr255Param)*displaymodeInfo->displayModeName); // the name of the mode
-
- // now get the DMDepthInfo into memory we own
- depthCount = displaymodeInfo->displayModeDepthBlockInfo->depthBlockCount;
- myDepthInfo = (DepthInfo*)NewPtrClear(depthCount * sizeof(DepthInfo));
-
- // set the info for the caller
- myIterateData->depthBlockCount = depthCount;
- myIterateData->depthBlocks = myDepthInfo;
-
- // and fill out all the entries
- if (depthCount) for (iCount=0; iCount < depthCount; iCount++)
- {
- myDepthInfo[iCount].depthSwitchInfo =
- *displaymodeInfo->displayModeDepthBlockInfo->depthVPBlock[iCount].depthSwitchInfo;
- myDepthInfo[iCount].depthVPBlock =
- *displaymodeInfo->displayModeDepthBlockInfo->depthVPBlock[iCount].depthVPBlock;
- }
- }
-
- void PrintAvailableVideoSettingsDM2 (GDHandle walkDevice,
- DMDisplayModeListIteratorUPP myModeIteratorProc,
- DMListIndexType theDisplayModeCount,
- DMListType *theDisplayModeList)
- {
- short jCount;
- short kCount;
- ListIteratorDataRec searchData;
- double_t refreshRate;
- unsigned long switchFlags;
- Boolean modeOk;
- OSErr error;
-
- searchData.depthBlocks = nil;
- // get the mode lists for this GDevice
- // printf ("\n about to start DMGetIndexedDisplayModeFromList loop\n");
- for (jCount=0; jCount<theDisplayModeCount; jCount++) // get info on all the resolution timings
- {
- DMGetIndexedDisplayModeFromList(*theDisplayModeList, jCount, 0, myModeIteratorProc, &searchData);
- // printf ("\n just did a DMGetIndexedDisplayModeFromList\n");
-
- // only if the mode is valid
- // if (searchData.displayModeTimingInfo.csTimingFlags & 1<<kModeValid)
- {
- // for all the depths for this resolution timing (mode)...
- printf("\nTiming mode: %d (or 0x%X) named “%s”\n",
- searchData.depthBlocks[0].depthSwitchInfo.csData,
- searchData.depthBlocks[0].depthSwitchInfo.csData,
- P2CStr(searchData.displayModeName));
-
- refreshRate = Fix2X (searchData.displayModeResolutionInfo.csRefreshRate);
- refreshRate = round (refreshRate);
- if (refreshRate == 0)
- printf ("Refresh rate: 0 (not defined in displayModeResolutionInfo.csRefreshRate)\n");
- else
- printf ("Refresh rate: %g\n", refreshRate);
-
- if (searchData.displayModeResolutionInfo.csResolutionFlags & 1<<kResolutionHasMultipleDepthSizes)
- printf("DisplayMode has different H&V per bit depth\n");
- else
- printf("DisplayMode does not have different H&V per bit depth\n");
-
- {
- char tempArr[6];
- ResType* tempPtr = (ResType* )&tempArr[0]; // Make a convenient ptr to assign the restype
- *tempPtr = searchData.displayModeTimingInfo.csTimingFormat; // contents of string are the resType
- tempArr[4] = 0; // null temp the string
- printf("Timing format: “%s”. Timing csData %d\n", tempArr, searchData.displayModeTimingInfo.csTimingData);
- }
-
- printf("Available depths:\n");
-
-
- if (searchData.depthBlockCount) for (kCount = 0; kCount < searchData.depthBlockCount; kCount++)
- {
- // print all the timing information
- printf(" Depth: %d, Depth mode: 0x%X, Resolution: %dH x %dV\n",
- searchData.depthBlocks[kCount].depthVPBlock.vpPixelSize,
- searchData.depthBlocks[kCount].depthSwitchInfo.csMode,
- searchData.depthBlocks[kCount].depthVPBlock.vpBounds.right,
- searchData.depthBlocks[kCount].depthVPBlock.vpBounds.bottom);
- // printf("Components per Pixel: %d, bits per Component: %d\n",
- // searchData.depthBlocks[kCount].depthVPBlock.vpCmpCount,
- // searchData.depthBlocks[kCount].depthVPBlock.vpCmpSize);
-
-
- }
-
- error = DMCheckDisplayMode(walkDevice,
- searchData.depthBlocks[0].depthSwitchInfo.csData,
- searchData.depthBlocks[0].depthSwitchInfo.csMode,
- &switchFlags,
- 0,
- &modeOk);
-
- if (noErr == error && modeOk)
- {
- printf("Switch flags = 0x%X\n", switchFlags);
- if (switchFlags & 1<<kNoSwitchConfirmBit)
- printf(" Confirmation not required,\n");
- else
- printf(" Confirmation required,\n");
- if (switchFlags & 1<<kDepthNotAvailableBit)
- printf(" Current depth not available in this mode,\n");
- else
- printf(" Current depth available in this mode,\n");
- if (switchFlags & 1<<kShowModeBit)
- printf(" Always shown,\n");
- else
- printf(" Not always shown,\n");
- if (switchFlags & 1<<kModeNotResizeBit)
- printf(" Not resizeable,\n");
- else
- printf(" Resizeable\n");
- }
-
- // timing flags
- printf("Timing flags = 0x%X\n",searchData.displayModeTimingInfo.csTimingFlags);
- if (searchData.displayModeTimingInfo.csTimingFlags & 1<<kModeValid)
- printf(" Valid,\n",searchData.displayModeTimingInfo.csTimingFlags);
- else
- printf(" Invalid,\n",searchData.displayModeTimingInfo.csTimingFlags);
- if (searchData.displayModeTimingInfo.csTimingFlags & 1<<kModeSafe)
- printf(" Safe,\n");
- else
- printf(" Unsafe,\n");
- if (searchData.displayModeTimingInfo.csTimingFlags & 1<<kModeDefault)
- printf(" Default,\n");
- else
- printf(" Not default,\n");
- if (searchData.displayModeTimingInfo.csTimingFlags & 1<<kModeShowNow)
- printf(" Always shown,\n");
- else
- printf(" Not always shown,\n");
- if (searchData.displayModeTimingInfo.csTimingFlags & 1<<kModeNotResize)
- printf(" Not resizeable,\n");
- else
- printf(" Resizeable,\n");
- if (searchData.displayModeTimingInfo.csTimingFlags & 1<<kModeRequiresPan)
- printf(" Requires pan.\n");
- else
- printf(" No pan.\n");
-
- // mode flags
- printf("Mode flags = 0x%X\n",searchData.displayModeFlags);
- if (searchData.displayModeFlags & 1<<0)
- printf(" Stripped,\n");
- else
- printf(" Not Stripped,\n");
- }
-
- if (searchData.depthBlocks)
- {
- DisposePtr ((Ptr)searchData.depthBlocks); // toss for this timing mode of this gdevice
- searchData.depthBlocks = nil; // init it just so we know
- }
- }
- }
-
-